package com.syf.core.service.run;

import cn.hutool.core.util.StrUtil;
import com.syf.core.engine.SyFrameContext;
import com.syf.core.exception.ExceptionUtils;
import com.syf.core.kit.resource.KitResourceReleaseController;
import com.syf.core.log.trace.SyfTraceIdConvert;
import com.syf.core.service.context.ServiceContext;
import com.syf.core.service.context.ServiceRequest;
import com.syf.core.service.context.ServiceResponse;
import com.syf.core.service.enums.ResponseFormatEnums;
import com.syf.core.service.run.chain.ServiceExecutionChain;
import com.syf.kit.SyIdGenerator;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.Callable;

@Slf4j
public class SyServiceCallable implements Callable<ServiceResponse> {
    private final ServiceRequest request;

    private final ServiceExecutionChain executionChain;

    private final SyFrameContext frameContext;

    private final KitResourceReleaseController kitResourceReleaseController;

    public SyServiceCallable(ServiceRequest request, ServiceExecutionChain executionChain, SyFrameContext frameContext, KitResourceReleaseController kitResourceReleaseController) {
        this.request = request;
        this.executionChain = executionChain;
        this.frameContext = frameContext;
        this.kitResourceReleaseController = kitResourceReleaseController;
    }

    @Override
    public ServiceResponse call() {

        ServiceContext context;
        try {
            // 设置ThreadLocal
            if (StrUtil.isBlank(request.getHead().getTraceId())) {
                SyIdGenerator idGenerator = frameContext.getToolKit(SyIdGenerator.class);
                request.getHead().setTraceId(idGenerator.getSnowFlackTraceId());
            }
            SyfTraceIdConvert.setTraceId(request.getHead().getTraceId());

            // 执行交易的process chain
            context = new ServiceContext(request, frameContext);
            executionChain.processed(context);

            return context.getResponse();
        } catch (Exception e) {
            log.error(ExceptionUtils.getExceptionStackInfo(e));
            return new ServiceResponse(ResponseFormatEnums.SERVICE_PROCESS_HAS_EXCEPTION);
        } finally {
            SyfTraceIdConvert.clear();
            // 释放kit中的各类资源，例如rdsdao、redisclient等
            kitResourceReleaseController.releaseAll();
        }
    }

    public ServiceRequest getRequest() {
        return request;
    }

    public ServiceExecutionChain getExecutionChain() {
        return executionChain;
    }

    public SyFrameContext getFrameContext() {
        return frameContext;
    }

    public KitResourceReleaseController getKitResourceReleaseController() {
        return kitResourceReleaseController;
    }
}
